﻿#ifndef __LUA_CALLER_H__
#define __LUA_CALLER_H__

#include "./def.h"
#include "./defaultconvertor.h"

#define PUSH_ARG_FIRST\
    TypeConvertor<P1> convertor1;\
	convertor1.SetLuaState(luaState);\
    narg += convertor1.SetValue(p1);
#define PUSH_ARG(n)\
    TypeConvertor<P##n> convertor##n;\
	convertor##n.SetLuaState(luaState);\
    narg += convertor##n.SetValue(p##n);
#define PUSH_ARGS(n) APPEND(REPEAT_,n)(PUSH_ARG,n)

#define DEF_CALLER(n)\
    template <TYPE_PARAMS(n)>\
    inline bool CallFunc(luaobj& funcobj, DEF_ARGS(n))\
    {\
        return CallFuncEx(m_luaState, funcobj, VARS(n));\
    }

#define DEF_THREAD_CALLER(n)\
    template <TYPE_PARAMS(n)>\
    inline bool CallThreadFunc(luathread& td, luaobj& funcobj, DEF_ARGS(n))\
    {\
        return CallFuncEx(td->GetThreadState(), funcobj, VARS(n));\
    }

#define DEF_CALLEREX(n)\
    template <TYPE_PARAMS(n)>\
    inline bool CallFuncEx(lua_State* luaState, luaobj& funcobj, DEF_ARGS(n))\
    {\
        if (NULL_OBJECT == funcobj->GetObj())\
        {\
            return false;\
        }\
        funcobj->PushObj(luaState);\
        int narg = 0;\
		PUSH_ARGS(n)\
        if (0 != lua_pcall(luaState, narg, 0, 0))\
        {\
			const char * szErr = lua_tostring(luaState, -1);\
			OutputDebugStringA(szErr);\
            lua_pop(m_luaState, 1);\
            return false;\
        }\
        return true;\
    }

#define DEF_CALLERS\
    DEF_CALLER(1)\
    DEF_CALLER(2)\
    DEF_CALLER(3)\
    DEF_CALLER(4)\
    DEF_CALLER(5)\
    DEF_CALLER(6)\
    DEF_CALLER(7)\
    DEF_CALLER(8)\
    DEF_CALLER(9)\
    DEF_CALLER(10)\
    DEF_CALLER(11)\
    DEF_CALLER(12)\
    DEF_CALLER(13)\
    DEF_CALLER(14)\
    DEF_CALLER(15)\
    DEF_CALLER(16)\
    DEF_CALLER(17)\
    DEF_CALLER(18)\
    DEF_CALLER(19)\
    DEF_CALLER(20)\
    DEF_CALLER(21)\
    DEF_CALLER(22)\
    DEF_CALLER(23)\
    DEF_CALLER(24)\
    DEF_CALLER(25)\
    DEF_CALLER(26)\
    DEF_CALLER(27)\
    DEF_CALLER(28)\
    DEF_CALLER(29)\
    DEF_CALLER(30)

#define DEF_THREAD_CALLERS\
	DEF_THREAD_CALLER(1)\
	DEF_THREAD_CALLER(2)\
	DEF_THREAD_CALLER(3)\
	DEF_THREAD_CALLER(4)\
	DEF_THREAD_CALLER(5)\
	DEF_THREAD_CALLER(6)\
	DEF_THREAD_CALLER(7)\
	DEF_THREAD_CALLER(8)\
	DEF_THREAD_CALLER(9)\
	DEF_THREAD_CALLER(10)\
	DEF_THREAD_CALLER(11)\
	DEF_THREAD_CALLER(12)\
	DEF_THREAD_CALLER(13)\
	DEF_THREAD_CALLER(14)\
	DEF_THREAD_CALLER(15)\
	DEF_THREAD_CALLER(16)\
	DEF_THREAD_CALLER(17)\
	DEF_THREAD_CALLER(18)\
	DEF_THREAD_CALLER(19)\
	DEF_THREAD_CALLER(20)\
	DEF_THREAD_CALLER(21)\
	DEF_THREAD_CALLER(22)\
	DEF_THREAD_CALLER(23)\
	DEF_THREAD_CALLER(24)\
	DEF_THREAD_CALLER(25)\
	DEF_THREAD_CALLER(26)\
	DEF_THREAD_CALLER(27)\
	DEF_THREAD_CALLER(28)\
	DEF_THREAD_CALLER(29)\
	DEF_THREAD_CALLER(30)

#define DEF_CALLEREXS\
	DEF_CALLEREX(1)\
	DEF_CALLEREX(2)\
	DEF_CALLEREX(3)\
	DEF_CALLEREX(4)\
	DEF_CALLEREX(5)\
	DEF_CALLEREX(6)\
	DEF_CALLEREX(7)\
	DEF_CALLEREX(8)\
	DEF_CALLEREX(9)\
	DEF_CALLEREX(10)\
	DEF_CALLEREX(11)\
	DEF_CALLEREX(12)\
	DEF_CALLEREX(13)\
	DEF_CALLEREX(14)\
	DEF_CALLEREX(15)\
	DEF_CALLEREX(16)\
	DEF_CALLEREX(17)\
	DEF_CALLEREX(18)\
	DEF_CALLEREX(19)\
	DEF_CALLEREX(20)\
	DEF_CALLEREX(21)\
	DEF_CALLEREX(22)\
	DEF_CALLEREX(23)\
	DEF_CALLEREX(24)\
	DEF_CALLEREX(25)\
	DEF_CALLEREX(26)\
	DEF_CALLEREX(27)\
	DEF_CALLEREX(28)\
	DEF_CALLEREX(29)\
	DEF_CALLEREX(30)

#endif